package com.health.yb.core.utils;

import com.health.yb.core.exception.CommonException;
import ma.glasnost.orika.BoundMapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author rjwang
 * @create 2019/4/29 10:40
 * @description 获取orika bean映射操作工厂
 */
public class MapperFactoryUtil {

    public static MapperFactory getMapperFactory() {
        return new DefaultMapperFactory.Builder().build();
    }

    /**
     * @param desc        原对象
     * @param targetClass 映射对象class
     * @description bean对象映射
     * @date 2019/4/29 11:37
     */
    public static <S, T> T beanTtoC(Object desc, Class<T> targetClass) {
        if (desc == null) {
            throw new CommonException("映射对象不能为空");
        }
        Class<S> descClass = (Class<S>) desc.getClass();
        MapperFactory mapperFactory = getMapperFactory();
        //注册字段映射
        mapperFactory.classMap(descClass, targetClass).byDefault().register();
        //执行映射 获取值
        BoundMapperFacade<S, T> boundMapperFacade = mapperFactory.getMapperFacade(descClass, targetClass);
        T target = boundMapperFacade.map((S) desc);
        return target;

    }

    /**
     * bean对象映射 排除字段
     *
     * @param desc        原对象
     * @param targetClass 映射对象class
     * @param excludes    需要排除的属性名
     * @date 2019/4/29 11:37
     */
    public static <S, T> T beanTtoC(Object desc, Class<T> targetClass, String[] excludes) {
        if (desc == null) {
            throw new CommonException("映射对象不能为空");
        }
        Class<S> descClass = (Class<S>) desc.getClass();
        MapperFactory mapperFactory = getMapperFactory();
        //注册字段映射
        ClassMapBuilder<S, T> classMapBuilder = mapperFactory.classMap(descClass, targetClass);
        for (String exclude : excludes) {
            classMapBuilder.exclude(exclude);
        }
        classMapBuilder.byDefault().register();
        //执行映射 获取值
        BoundMapperFacade<S, T> boundMapperFacade = mapperFactory.getMapperFacade(descClass, targetClass);
        T target = boundMapperFacade.map((S) desc);
        return target;
    }

    /**
     * bean对象映射 忽略null
     *
     * @param desc        原对象
     * @param targetClass 映射对象class
     * @param mapNulls    需要排除的属性名
     * @date 2019/4/29 11:37
     */
    public static <S, T> T beanTtoC(Object desc, Class<T> targetClass, Boolean mapNulls) {
        if (desc == null) {
            throw new CommonException("映射对象不能为空");
        }
        Class<S> descClass = (Class<S>) desc.getClass();
        MapperFactory mapperFactory = getMapperFactory();
        //注册字段映射
        mapperFactory.classMap(descClass, targetClass).mapNulls(mapNulls).byDefault().register();
        //执行映射 获取值
        BoundMapperFacade<S, T> boundMapperFacade = mapperFactory.getMapperFacade(descClass, targetClass);
        T target = boundMapperFacade.map((S) desc);
        return target;
    }

    /**
     * 集合与集合之间的对象映射
     *
     * @param descs       原对象list集合
     * @param targetClass 返回list集合中的泛型class
     * @return
     * @throws
     * @version 1.0
     * @author rjwang
     * @date 2019/6/6 15:02
     */
    public static <S, T> List<T> beanLTtoLC(List<S> descs, Class<T> targetClass) {
        if (CollectionUtils.isEmpty(descs)) {
            throw new CommonException("映射对象不能为空");
        }
        List<T> ts = new ArrayList<>();
        for (S desc : descs) {
            T t = beanTtoC(desc, targetClass);
            ts.add(t);
        }
        return ts;
    }


    /**
     * @param desc        原对象
     * @param targetClass 映射对象class
     * @param fieldMap    不同字段映射map : key是原对象的字段，value 是映射实体的字段
     * @return
     * @description bean对象映射
     * @date 2019/4/29 11:37
     */
    public static <S, T> T beanTtoC(Object desc, Class<T> targetClass, Map<String, String> fieldMap) throws Exception {
        if (desc == null) {
            throw new CommonException("映射对象不能为空");
        }
        Class<S> descClass = (Class<S>) desc.getClass();
        //获取映射工厂
        MapperFactory mapperFactory = getMapperFactory();
        //注册映射的两个类
        ClassMapBuilder<S, T> classMapBuilder = mapperFactory.classMap(descClass, targetClass);
        //设置不同属性对应关系
        for (Map.Entry<String, String> stringEntry : fieldMap.entrySet()) {
            String key = stringEntry.getKey();
            String value = stringEntry.getValue();
            classMapBuilder.field(key, value);
        }
        //剩余字段默认按照属性名映射，并且注册
        classMapBuilder.byDefault().register();
        //执行映射，返回对象
        BoundMapperFacade<S, T> boundMapperFacade = mapperFactory.getMapperFacade(descClass, targetClass);
        T target = boundMapperFacade.map((S) desc);
        return target;

    }


}
